﻿using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Freebase4net.Rest
{
    public class RestClient
    {
        private HttpClient _httpClient;
        private WebClient _webClient;
        private List<Parameter> _parameters;

        public string BaseUrl { get; set; }

        public RestClient()
        {
            _httpClient = new HttpClient();
            _webClient = new WebClient();
            _parameters = new List<Parameter>();
        }

        public async Task<RestResponseMessage> ExecuteResultAsync(string url = "")
        {
            var message = ExecuteResultCommon(url);

            HttpResponseMessage response = await _httpClient.GetAsync(message.RequestUrl);
            message.StatusCode = response.StatusCode;

            if (!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.BadRequest)
                return message;

            message.Content = await response.Content.ReadAsStringAsync();

            return message;
        }

        /// <summary>
        /// Load page from passed url or BaseUrl
        /// </summary>
        /// <param name="url">Can be empty, then BaseeUrl will be used</param>
        /// <returns>Object that represents http status code and content as string</returns>
        public RestResponseMessage ExecuteResult(string url = "")
        {
            var message = ExecuteResultCommon(url);
            try
            {
                message.Content = _webClient.DownloadString(message.RequestUrl);
                message.StatusCode = HttpStatusCode.OK;
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    var response = ex.Response as HttpWebResponse;
                    if (response != null)
                    {
                        message.Content = response.StatusDescription;
                        message.StatusCode = response.StatusCode;
                    }
                }
            }
            return message;
        }

        /// <summary>
        /// Create url and add paramters to it
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private RestResponseMessage ExecuteResultCommon(string url)
        {
            RestResponseMessage message = new RestResponseMessage();
            if (string.IsNullOrEmpty(url))
                url = BaseUrl;

            url = string.Format("{0}{1}", url, CreateQueryString());
            message.RequestUrl = url;
            return message;
        }

        public void AddParameter(string name, string value)
        {
            _parameters.Add(new Parameter { Name = name, Value = value });
        }

        /// <summary>
        /// Create query string using paramteres list
        /// </summary>
        /// <returns></returns>
        private string CreateQueryString()
        {
            StringBuilder result = new StringBuilder();
            result.Append("?");
            foreach (var param in _parameters)
            {
                result.Append(param.ToString());
                result.Append("&");
            }
            result = result.Remove(result.Length - 1, 1);
            return result.ToString();
        }

        private DataFormat _requestFormat;
        public DataFormat RequestFormat
        {
            get
            {
                return _requestFormat;
            }
            set
            {
                if (value == DataFormat.Json)
                {
                    _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                }
                _requestFormat = value;
            }
        }
    }
}
